﻿using System;
using System.Drawing;
using System.Windows;
using System.Windows.Media.Imaging;

namespace HB.WpfEx
{
    public class ImageGraphics : IDisposable
    {
        WriteableBitmap map;
        Bitmap bmap;
        Graphics G;
        int Width;
        int Height;
        byte[] BgImageData;
        int BgStride = 0;
        /// <summary>
        /// 创建Graphics对象
        /// </summary>
        /// <param name="containerImage">图像容器</param>
        /// <param name="targetWidth">绘制目标宽度</param>
        /// <param name="targetHeight">绘制目标高度</param>
        public ImageGraphics(System.Windows.Controls.Image containerImage, int targetWidth, int targetHeight)
        {
            map = new WriteableBitmap(targetWidth, targetHeight, 96, 96, System.Windows.Media.PixelFormats.Bgr32, null);
            bmap = new Bitmap(map.PixelWidth, map.PixelHeight, map.BackBufferStride, System.Drawing.Imaging.PixelFormat.Format32bppPArgb, map.BackBuffer);
            G = Graphics.FromImage(bmap);
            containerImage.Source = map;
            this.Width = targetWidth;
            this.Height = targetHeight;
        }

        /// <summary>
        /// 创建含有背景图的Graphics对象
        /// </summary>
        /// <param name="containerImage"></param>
        /// <param name="bgImage">背景图</param>
        public ImageGraphics(System.Windows.Controls.Image containerImage, BitmapSource bgImage)
        {
            if (bgImage.Format == System.Windows.Media.PixelFormats.Bgr32)
            {
                map = new WriteableBitmap(bgImage.PixelWidth, bgImage.PixelHeight, 96, 96, bgImage.Format, null);
                bmap = new Bitmap(map.PixelWidth, map.PixelHeight, map.BackBufferStride, System.Drawing.Imaging.PixelFormat.Format32bppArgb, map.BackBuffer);
                BgImageData = new byte[bgImage.PixelHeight * bgImage.PixelWidth * 4];
                BgStride = 4 * bgImage.PixelWidth;
                bgImage.CopyPixels(BgImageData, BgStride, 0);

            }
            if (bgImage.Format == System.Windows.Media.PixelFormats.Bgr24)
            {
                map = new WriteableBitmap(bgImage.PixelWidth, bgImage.PixelHeight, 96, 96, bgImage.Format, null);
                bmap = new Bitmap(map.PixelWidth, map.PixelHeight, map.BackBufferStride, System.Drawing.Imaging.PixelFormat.Format24bppRgb, map.BackBuffer);
                BgStride = bgImage.PixelWidth * 3;
                BgImageData = new byte[bgImage.PixelHeight * BgStride];
                bgImage.CopyPixels(BgImageData, 3 * bgImage.PixelWidth, 0);
            }
            if (map == null) { throw new Exception("only support bgr32 or bgr24"); }
            SetToBgImage(true);
            G = Graphics.FromImage(bmap);
            containerImage.Source = map;
            this.Width = bgImage.PixelWidth;
            this.Height = bgImage.PixelHeight;
        }
        /// <summary>
        /// 使用Graphics并更新到界面
        /// </summary>
        /// <param name="action"></param>
        public void UsingGraphics(Action<Graphics> action)
        {
            UsingGraphics(new System.Windows.Int32Rect(0, 0, Width, Height), action);
        }
        /// <summary>
        /// 使用Graphics并更新到界面并指定更新区域
        /// </summary>
        /// <param name="rect"></param>
        /// <param name="action"></param>
        public void UsingGraphics(System.Windows.Int32Rect rect, Action<Graphics> action)
        {
            map.Dispatcher.Invoke(new Action(() =>
            {
                map.Lock();
                action.Invoke(G);
                map.AddDirtyRect(rect);
                map.Unlock();
            }));
        }
        /// <summary>
        /// 设置为背景图片
        /// </summary>
        /// <param name="notify">是否通知UI修改</param>
        public void SetToBgImage(bool notify = false)
        {
            if (BgImageData != null)
            {
                map.Dispatcher.Invoke(new Action(() =>
                          {
                              map.Lock();
                              map.WritePixels(new System.Windows.Int32Rect(0, 0, map.PixelWidth, map.PixelHeight), BgImageData, BgStride, 0);
                              if (notify)
                              {
                                  map.AddDirtyRect(new Int32Rect(0, 0, map.PixelWidth, map.PixelHeight));
                              }
                              map.Unlock();
                          }));
            }

        }
        /// <summary>
        /// 去除所有内容
        /// </summary>
        /// <param name="col"></param>
        public void Clear(Color col)
        {
            UsingGraphics(g =>
            {
                g.Clear(col);
            });
        }
        /// <summary>
        /// 释放占用资源
        /// </summary>
        public void Dispose()
        {
            G?.Dispose();
            bmap?.Dispose();
        }
        /// <summary>
        /// 将当前绘制效果保存为png
        /// </summary>
        /// <param name="fileName"></param>
        public void SaveToPng(string fileName)
        {
            bmap.Save(fileName, System.Drawing.Imaging.ImageFormat.Png);
        }
    }
}
